/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_seek_hal.h"
#include "sle_seek_hdi.h"
#include "sle_hilog.h"
#include "sle_loader_hal.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static SleSeekHdiOpts* g_sleSeekHalOpts = NULL;
static SleSeekHdiCallbacks* g_sleSeekHdiCbs = NULL;
static SleSeekHalCallbacks* g_sleSeekHalCbs = NULL;

static void OnSleHdiStartSeekCallback(SleHdiErrorCode errCode)
{
    SLE_LOGI("OnSleHdiStartSeekCallback errCode(0x%{public}08X)", errCode);
    if (g_sleSeekHalCbs != NULL && g_sleSeekHalCbs->OnSeekHalEnableSeekCb != NULL) {
        g_sleSeekHalCbs->OnSeekHalEnableSeekCb(SleHalGetErrorCode(errCode));
    }
}

static void OnSleHdiStopSeekCallback(SleHdiErrorCode errCode)
{
    SLE_LOGI("OnSleHdiStopSeekCallback errCode(0x%{public}08X)", errCode);
    if (g_sleSeekHalCbs != NULL && g_sleSeekHalCbs->OnSeekHalDisableSeekCb != NULL) {
        g_sleSeekHalCbs->OnSeekHalDisableSeekCb(SleHalGetErrorCode(errCode));
    }
}

static void OnSleHdiSeekResultCallback(const SleSeekResult *seekResultData)
{
    if (g_sleSeekHalCbs != NULL && g_sleSeekHalCbs->OnSeekHalSeekResultCb != NULL) {
        g_sleSeekHalCbs->OnSeekHalSeekResultCb(seekResultData);
    }
}

SleHalErrorCode InitSleSeekHal(void)
{
    SLE_LOGI("InitSleSeekHal");
    SLE_ASSERT_AND_RETURN_RET_LOG(g_sleSeekHalOpts == NULL, SLE_HAL_SUCCESS, "sleSeekHal has been Inited");
    SleHalErrorCode ret = SLE_HAL_ERR_UNKNOWN;
    g_sleSeekHalOpts = (SleSeekHdiOpts*)malloc(sizeof(SleSeekHdiOpts));
    ret = GetSleSeekHalOpts(g_sleSeekHalOpts);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "GetSleSeekHalOpts fail(%{public}d)", ret);
    SLE_ASSERT_AND_RETURN_RET(g_sleSeekHalOpts != NULL, SLE_HAL_ERR_UNKNOWN);
    if(g_sleSeekHdiCbs == NULL) {
        g_sleSeekHdiCbs = (SleSeekHdiCallbacks*)malloc(sizeof(SleSeekHdiCallbacks));
        g_sleSeekHdiCbs->OnSeekStartCb = OnSleHdiStartSeekCallback;
        g_sleSeekHdiCbs->OnSeekStopCb = OnSleHdiStopSeekCallback;
        g_sleSeekHdiCbs->OnSeekResultCb = OnSleHdiSeekResultCallback;
        SLE_ASSERT_AND_RETURN_RET_LOG(g_sleSeekHdiCbs != NULL, SLE_HAL_ERR_DRIVER_OR_SYSTEM, "SleHal or SleDriver has not been inited");      
    }
    SleHdiErrorCode result = g_sleSeekHalOpts->registerSeeCbks(g_sleSeekHdiCbs);
    ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "registerSeeCbks fail(0x%{public}08X)", result);
    g_sleSeekHalCbs = (SleSeekHalCallbacks*)malloc(sizeof(SleSeekHalCallbacks));
    return ret;
}

SleHalErrorCode DeinitSleSeekHal(void)
{
    SLE_LOGI("DeinitSleSeekHal");
    SLE_ASSERT_AND_RETURN_RET_LOG(g_sleSeekHalOpts != NULL, SLE_HAL_SUCCESS, "sleSeekHal has not been Inited");
    free(g_sleSeekHalOpts);
    g_sleSeekHalOpts = NULL;
    free(g_sleSeekHdiCbs);
    g_sleSeekHalCbs = NULL;
    free(g_sleSeekHalCbs);
    g_sleSeekHalCbs = NULL;
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode SleSeekHalSetSeekParam(const SleSeekParam *param)
{
    SLE_LOGI("SleSeekHalSetSeekParam");
    for (int i = 0; i < SLE_SEEK_PHY_MAX; i++) {
        SLE_LOGD("\t  channel[%{public}d]: type(%hu), interval(%{public}d), window(%{public}d)", i, param->type[i], param->interval[i], param->window[i]);
    }
    SLE_ASSERT_AND_RETURN_RET(g_sleSeekHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(param != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode result = g_sleSeekHalOpts->setSeekParam(param);
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "setSeekParam fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleSeekHalStartSeek(void)
{
    SLE_LOGI("SleSeekHalStartSeek");
    SLE_ASSERT_AND_RETURN_RET(g_sleSeekHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SleHdiErrorCode result = g_sleSeekHalOpts->startSeek();
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "startSeek fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleSeekHalStopSeek(void)
{
    SLE_LOGI("SleSeekHalStopSeek");
    SLE_ASSERT_AND_RETURN_RET(g_sleSeekHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SleHdiErrorCode result = g_sleSeekHalOpts->stopSeek();
    SleHalErrorCode ret = SleHalGetErrorCode(result);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "stopSeek fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode SleSeekHalRegisterCallback(const SleSeekHalCallbacks *seekHalcallback)
{
    SLE_LOGI("SleSeekHalRegisterCallback");
    SLE_ASSERT_AND_RETURN_RET(g_sleSeekHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(seekHalcallback != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(g_sleSeekHalCbs, seekHalcallback, sizeof(SleSeekHalCallbacks));
    return SLE_HAL_SUCCESS;
}
